import * as THREE from 'three';
import {Face3, Geometry} from "three/examples/jsm/deprecated/Geometry";
import {ShapeGeometry} from "three";

/**
 * 画点
 * @param pointGroup
 * @param point
 * @param options
 * @returns {Points}
 */
export function drawPoint(pointGroup, point, options) {
    const {color, transparent, opacity, side, depthTest} = options || {};
    const material = new THREE.PointsMaterial({
        color: color || 0xFF0000,
        transparent: transparent || true,
        opacity: opacity || 1,
        side: side || THREE.FrontSide,
        depthTest: depthTest || true
    });
    //设置具有几何顶点的几何（Geometry）或缓冲区几何（BufferGeometry）设置顶点位置，看名字就知道了，一个是直接将数据保存在js里面的，另一个是保存在WebGL缓冲区内的，而且肯定保存到WebGL缓冲区内的效率更高
    const geometry = new Geometry();
    geometry.vertices.push(point);
    //使用Line方法将线初始化
    const p = new THREE.Points(geometry, material);
    p.name = 'point';
    pointGroup.add(p);
    return p;
}

/**
 * 画线
 * @param lineGroup 线添加到指定的组或者Object3D
 * @param pointList 线的点
 * @param options {color, transparent, opacity, side, depthTest, isLine}
 * @returns {Mesh} 线
 */
export function drawLine(lineGroup, pointList, options) {
    const {color, transparent, opacity, side, depthTest, isLine} = options || {};
    const material = new THREE.LineBasicMaterial({
        color: color || 0xffFF00,
        transparent: transparent || true,
        opacity: opacity || 1,
        side: side || THREE.FrontSide,
        depthTest: depthTest || true
    });
    //设置具有几何顶点的几何（Geometry）或缓冲区几何（BufferGeometry）设置顶点位置，看名字就知道了，一个是直接将数据保存在js里面的，另一个是保存在WebGL缓冲区内的，而且肯定保存到WebGL缓冲区内的效率更高
    const geometry = new Geometry();
    pointList.forEach(value => {
        geometry.vertices.push(new THREE.Vector3(...value));
    });
    //使用Line方法将线初始化
    const line = new THREE[!isLine ? 'LineLoop' : 'Line'](geometry, material);
    line.name = 'line';
    lineGroup.add(line);
    return line;
}

/**
 * 画面
 * @param faceGroup 面添加到指定的组或者Object3D
 * @param pointList 面的点
 * @param options {color, transparent, opacity, side, depthTest}
 * @returns {Mesh} 面
 */
export function drawFace(faceGroup, pointList, options) {
    const {color, transparent, opacity, side, depthTest} = options || {};
    const geometry = new Geometry();

    pointList.forEach(points => {
        geometry.vertices.push(new THREE.Vector3(...points));
    });
    const vector3 = new THREE.Vector3();
    const c = new THREE.Color(0xffffff);
    for (let i = 2; i < pointList.length; i++) geometry.faces.push(new Face3(0, i - 1, i, vector3, c, i));

    const material = new THREE.MeshBasicMaterial({
        color: color || 0xff0000,
        transparent: transparent || true,
        opacity: opacity || 1,
        side: side || THREE.FrontSide,
        depthTest: depthTest || true
    });
    const face = new THREE.Mesh(geometry, material);
    face.name = 'face';
    faceGroup.add(face);
    return face;
}

/**
 * 画面
 * @param faceGroup 面添加到指定的组或者Object3D
 * @param pointList 面的点
 * @param options {color, transparent, opacity, side, depthTest}
 * @returns {Mesh} 面
 */
export function drawConcaveFace(faceGroup, pointList, options) {
    const {color, transparent, opacity, side, depthTest} = options || {};
    // 用来创建凹包多边形的点,一定要按顺序哦
    let points = pointList || [];
    let list = [];// 用来装点位的数组

    // 将目标数组改成Vector2 这里默认去掉高度y,当然如果你喜欢可以用其他轴的
    for (let i = 0; i < points.length; i++) list.push(new THREE.Vector2(points[i][0], points[i][2]));

    // 用这些点位生成一个 Geometry
    let geometry = new ShapeGeometry(new THREE.Shape(list));

    const material = new THREE.MeshBasicMaterial({
        color: color || 0xff0000,
        transparent: transparent || true,
        opacity: opacity || .5,
        side: side || THREE.BackSide,
        depthTest: depthTest || true
    });

    // 这就是你要的多边形啦
    let face = new THREE.Mesh(geometry, material);
    face.name = 'face';
    face.rotateX(Math.PI / 2);
    faceGroup.add(face);
    face.position.setY(1);
    return face;
}

/**
 * 让模型居中
 * @param camera
 * @param model
 */
export function setModelCenter(camera, model) {
    model.updateWorldMatrix();
    const box = new THREE.Box3().setFromObject(model);
    const boxSize = box.getSize();
    const center = box.getCenter(new THREE.Vector3());
    model.translateY(-center.y);
    model.translateX(-center.x);
    model.translateZ(-center.z);
    // model.position.copy(center);
    if (boxSize.x > boxSize.y) {
        camera.position.z = boxSize.x * -1;
        camera.position.y = boxSize.x
    } else {
        camera.position.z = boxSize.y * -1;
        camera.position.y = boxSize.y
    }
    camera.lookAt(0, 0, 0);
}

export function cameraMoveLookModel(camera, model) {
    model.updateWorldMatrix()
    const box = new THREE.Box3().setFromObject(model);
    const boxSize = box.getSize();
    console.log('boxSize', boxSize)
    const center = box.getCenter(new THREE.Vector3());
    console.log('center', center)
    // camera.position.copy(center.setScalar(500))
    // camera.lookAt(model.getWorldPosition())
    const axesHelper = new THREE.AxesHelper(1000);
    axesHelper.position.copy(boxSize)
    model.parent.add(axesHelper)

}

/**
 * 透视相机和正交相机的响应式控制视图大小
 * @param renderer
 * @param camera
 * @param width
 * @param height
 */
export function canvasResize(renderer, camera, width, height) {
    if (camera.type === 'PerspectiveCamera') {
        camera.aspect = width / height;
    } else if (camera.type === 'OrthographicCamera') {
        camera.left = -width;
        camera.right = width;
        camera.top = height;
        camera.bottom = -height;
    }
    camera.updateProjectionMatrix();
    renderer.setSize(width, height, false);
}

export default {
    drawPoint,
    drawLine,
    drawFace,
    drawConcaveFace,
    setModelCenter,
    canvasResize
};

